JAVA-6168: QE prefix/suffix/substring GA + rename Text API to String#2010
JAVA-6168: QE prefix/suffix/substring GA + rename Text API to String#2010nhachicha wants to merge 26 commits into
Conversation
…ncryptOptionsHelper
Provides GA support for QE 'prefix'/'suffix' query types and the 'string' algorithm (formerly 'textPreview'), and restores 'prefixPreview'/'suffixPreview' for pre-9.0 servers. Required by the Text->String API rename.
Updates testing/resources/specifications 4484038..8990543, bringing the GA QE-Text unified tests and String Explicit Encryption prose test (DRIVERS-3321, DRIVERS-3470).
libmongocrypt 1.20.0 adds stable support for substring queries (the GA 'substring' query type), unblocking DRIVERS-3540/JAVA-6244.
…se GA/preview split) - Un-skip the QE-Text-substring GA unified spec test (now supported via libmongocrypt 1.20.0). - Prose test 27: split substring cases 5/6 into GA (substring, server 9.0+/libmongocrypt 1.20+) and preview (substringPreview, server pre-9.0) paths using the new substring-preview collection; update seed strMaxQueryLength to 6; gate cases 10/11 to pre-9.0 per the updated spec.
There was a problem hiding this comment.
Pull request overview
Promotes Queryable Encryption explicit-encryption string queries from the preview “Text” API to the GA “String” API surface, adds StringOptions, and bumps bundled libmongocrypt to 1.20.0 to enable GA prefix/suffix/substring behavior across server versions.
Changes:
- Introduces
StringOptionsandEncryptOptions.stringOptions(...), while deprecatingTextOptions/EncryptOptions.textOptions(...)and mapping new options through the existing libmongocrypt “text options” document. - Updates functional and unit tests to exercise GA (
prefix/suffix/substring) vs pre-9.0 preview (*Preview) queryType behavior. - Updates
mongodb-cryptpackaging to download libmongocrypt 1.20.0 and adjusts GPG verification homedir handling to avoid macOS socket path limits.
Reviewed changes
Copilot reviewed 11 out of 12 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| mongodb-crypt/src/main/com/mongodb/internal/crypt/capi/MongoExplicitEncryptOptions.java | Updates internal Javadoc to reflect the algorithm name change to "String". |
| mongodb-crypt/build.gradle.kts | Bumps bundled libmongocrypt to 1.20.0 and moves GPG homedir to system temp to avoid macOS path-length failures. |
| driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTestModifications.java | Removes skip for the substring unified test now that it’s supported. |
| driver-sync/src/test/functional/com/mongodb/client/AbstractClientEncryptionTextExplicitEncryptionTest.java | Reworks QE prose-style functional tests to cover GA vs preview query types and adds additional cases. |
| driver-core/src/test/unit/com/mongodb/internal/client/vault/EncryptOptionsHelperTest.java | Adds unit tests for mapping StringOptions (and deprecated fallback) into the libmongocrypt options document. |
| driver-core/src/test/unit/com/mongodb/client/model/vault/StringOptionsTest.java | Adds unit tests for the new StringOptions value object. |
| driver-core/src/test/unit/com/mongodb/client/model/vault/EncryptOptionsTest.java | Adds unit tests for EncryptOptions storing stringOptions and deprecated textOptions. |
| driver-core/src/main/com/mongodb/internal/client/vault/EncryptOptionsHelper.java | Implements StringOptions → libmongocrypt “text options” document mapping with deprecated fallback. |
| driver-core/src/main/com/mongodb/client/model/vault/TextOptions.java | Deprecates TextOptions and adjusts defaults for boolean flags. |
| driver-core/src/main/com/mongodb/client/model/vault/StringOptions.java | Adds the new StringOptions API and associated documentation. |
| driver-core/src/main/com/mongodb/client/model/vault/EncryptOptions.java | Adds stringOptions accessors, deprecates textOptions, and updates Javadocs/toString accordingly. |
| .gitignore | Ignores docs/superpowers/. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| skipVerify.set(skipCryptVerify) | ||
| expectedFingerprint.set("F2F5BF4ABF517E039AFCADAA81F1404DEBACA586") | ||
| gnupgHome.set(layout.buildDirectory.dir("jnaLibs/gnupg")) | ||
| // Keep the scratch GPG keyring under the system temp dir, not the module build dir. gpg derives |
There was a problem hiding this comment.
This fix an issue where gpg invocation used to fail locally when invoked from Gradle/IDE under a deeply nested directories. Worth checking under Windows as well cc @strogiyotec
…ses 10/11, precedence test - Update EncryptOptions/StringOptions Javadocs: substring is GA (queryType 'substring', server 9.0+), 'substringPreview' is the deprecated pre-9.0 alias (was still documented as experimental/preview). - Prose test cases 10/11 (auto-encrypted substring ci-di): run on server 9.0+ (assumeTrue(gaSupported)), matching the substring-ci-di 9.0+ setup requirement and the prefix/suffix ci-di cases 8/9. The spec's 'skip on 9.0.0+' contradicts its own setup; TODO-JAVA-6244 pending upstream clarification. - Add EncryptOptionsHelper precedence test: stringOptions wins when both stringOptions and textOptions set.
| /** | ||
| * The QueryType. | ||
| * | ||
| * <p>Currently, we support only "equality", "range", "prefixPreview", "suffixPreview" or "substringPreview" queryType.</p> | ||
| * <p>It is an error to set queryType when the algorithm is not "Indexed", "Range" or "TextPreview".</p> | ||
| * <p>Currently, we support only "equality", "range", "prefix", "suffix", "substring", "prefixPreview", | ||
| * "suffixPreview" or "substringPreview" queryType.</p> |
There was a problem hiding this comment.
Fixed in f39e5e2. getQueryType()'s Javadoc now points to queryType(String) for the supported-types list, so the two can't drift apart.
| * @since 5.6 | ||
| * @mongodb.server.release 8.2 | ||
| * @mongodb.driver.manual /core/queryable-encryption/ queryable encryption | ||
| * @deprecated Use {@link StringOptions} instead. |
There was a problem hiding this comment.
TextOptions is the deprecated pre-rename type kept for backward compatibility, so it intentionally retains its "Text" naming/wording, and its @deprecated tag already points to StringOptions. :driver-core:javadoc builds clean, so leaving as-is.
| private static final ServerVersion REQUIRED_LIB_MONGOCRYPT_VERSION = new ServerVersion(asList(1, 19, 1)); | ||
| // GA "substring" (server 9.0+) needs libmongocrypt 1.20+; prefix/suffix GA and the preview paths need only 1.19/1.18. | ||
| private static final ServerVersion SUBSTRING_GA_LIB_MONGOCRYPT_VERSION = new ServerVersion(asList(1, 20, 0)); |
There was a problem hiding this comment.
Fixed in f39e5e2 — reworded to note the class-level 1.19.1 minimum already covers prefix/suffix GA and the pre-9.0 preview query types, while GA substring additionally needs 1.20.
| /** | ||
| * The Text Options. | ||
| * The String Options. | ||
| * | ||
| * <p>Only applies when algorithm is "TextPreview".</p> | ||
| * <p>Only applies when algorithm is "String". The method name mirrors the libmongocrypt {@code textOptions} | ||
| * BSON field, which is unchanged.</p> | ||
| * | ||
| * @param textOptions the text options | ||
| * @param textOptions the string options | ||
| * @return this |
There was a problem hiding this comment.
Fixed in f39e5e2 — the @param now reads "the string options, as a BSON document" to distinguish it from the public StringOptions type.
| * BSON field, which is unchanged.</p> | ||
| * | ||
| * @param textOptions the text options | ||
| * @param textOptions the string options |
There was a problem hiding this comment.
Fixed in f39e5e2 — the @param now reads "the string options, as a BSON document" to distinguish it from the public StringOptions type.
| /** | ||
| * Text options for a Queryable Encryption field that supports text queries. | ||
| * | ||
| * <p>Note: TextOptions is in Alpha and subject to backwards breaking changes. | ||
| * | ||
| * @since 5.6 | ||
| * @mongodb.server.release 8.2 | ||
| * @mongodb.driver.manual /core/queryable-encryption/ queryable encryption | ||
| * @deprecated Use {@link StringOptions} instead. | ||
| */ |
There was a problem hiding this comment.
TextOptions is the deprecated pre-rename type kept for backward compatibility, so it intentionally retains its "Text" naming/wording, and its @deprecated tag already points to StringOptions. :driver-core:javadoc builds clean, so leaving as-is.
| /** | ||
| * The Text Options. | ||
| * The String Options. | ||
| * | ||
| * <p>Only applies when algorithm is "TextPreview".</p> | ||
| * <p>Only applies when algorithm is "String". The method name mirrors the libmongocrypt {@code textOptions} | ||
| * BSON field, which is unchanged.</p> | ||
| * | ||
| * @param textOptions the text options | ||
| * @param textOptions the string options | ||
| * @return this | ||
| * @since 5.6 |
There was a problem hiding this comment.
Fixed in f39e5e2 — the @param now reads "the string options, as a BSON document" to distinguish it from the public StringOptions type.
| * BSON field, which is unchanged.</p> | ||
| * | ||
| * @param textOptions the text options | ||
| * @param textOptions the string options |
There was a problem hiding this comment.
Fixed in f39e5e2 — the @param now reads "the string options, as a BSON document" to distinguish it from the public StringOptions type.
| * <p>Currently, we support only "equality", "range", "prefix", "suffix", "substring", "prefixPreview", | ||
| * "suffixPreview" or "substringPreview" queryType.</p> | ||
| * <p>The "prefix", "suffix", "substring", "prefixPreview", "suffixPreview" and "substringPreview" query types are | ||
| * only valid with the "String" algorithm. "prefixPreview"/"suffixPreview"/"substringPreview" are deprecated | ||
| * aliases supported for servers 8.2 to pre-9.0; use "prefix"/"suffix"/"substring" on server 9.0+.</p> | ||
| * <p>It is an error to set queryType when the algorithm is not "Indexed", "Range" or "String".</p> |
There was a problem hiding this comment.
Fixed in f39e5e2. getQueryType()'s Javadoc now points to queryType(String) for the supported-types list, so the two can't drift apart.
| * <p>Only applies when algorithm is "String". The method name mirrors the libmongocrypt {@code textOptions} | ||
| * BSON field, which is unchanged.</p> | ||
| * | ||
| * @param textOptions the text options | ||
| * @param textOptions the string options | ||
| * @return this |
There was a problem hiding this comment.
Fixed in f39e5e2 — the @param now reads "the string options, as a BSON document" to distinguish it from the public StringOptions type.
| * <p>Currently, we support only "equality", "range", "prefix", "suffix", "substring", "prefixPreview", | ||
| * "suffixPreview" or "substringPreview" queryType.</p> | ||
| * <p>The "prefix", "suffix", "substring", "prefixPreview", "suffixPreview" and "substringPreview" query types are | ||
| * only valid with the "String" algorithm. "prefixPreview"/"suffixPreview"/"substringPreview" are deprecated | ||
| * aliases supported for servers 8.2 to pre-9.0; use "prefix"/"suffix"/"substring" on server 9.0+.</p> | ||
| * <p>It is an error to set queryType when the algorithm is not "Indexed", "Range" or "String".</p> |
There was a problem hiding this comment.
Fixed in f39e5e2. getQueryType()'s Javadoc now points to queryType(String) for the supported-types list, so the two can't drift apart.
| * @since 5.6 | ||
| * @mongodb.server.release 8.2 | ||
| * @mongodb.driver.manual /core/queryable-encryption/ queryable encryption | ||
| * @deprecated Use {@link StringOptions} instead. | ||
| */ |
There was a problem hiding this comment.
TextOptions is the deprecated pre-rename type kept for backward compatibility, so it intentionally retains its "Text" naming/wording, and its @deprecated tag already points to StringOptions. :driver-core:javadoc builds clean, so leaving as-is.
…n comment - EncryptOptions.getQueryType() javadoc referenced only equality/range; point it to queryType(String) so it stays consistent with the supported-types list. - MongoExplicitEncryptOptions.textOptions @param: clarify it takes the string options as a BSON document. - Prose test: reword the libmongocrypt version comment to reflect the class-level 1.19.1 floor.
| /** | ||
| * The Text Options. | ||
| * The String Options. | ||
| * | ||
| * <p>Only applies when algorithm is "TextPreview".</p> | ||
| * <p>Only applies when algorithm is "String". The method name mirrors the libmongocrypt {@code textOptions} | ||
| * BSON field, which is unchanged.</p> | ||
| * | ||
| * @param textOptions the text options | ||
| * @param textOptions the string options | ||
| * @return this |
There was a problem hiding this comment.
The @param was already clarified to "the string options, as a BSON document". The parameter name intentionally mirrors the libmongocrypt textOptions BSON field it maps to (an internal binding class), and the description now makes the BSON-document type explicit, so I'll leave the name as-is.
| // Download the libmongocrypt per-platform tarballs (and their signatures) to jnaDownloadsDir. | ||
| // To upgrade: change downloadRevision, run `./gradlew clean downloadJnaLibs`, and verify the build. | ||
| val downloadRevision = "1.18.1" | ||
| val downloadRevision = "1.20.0" | ||
| val downloadUrlBase = "https://github.com/mongodb/libmongocrypt/releases/download/$downloadRevision" |
There was a problem hiding this comment.
Fixed in the follow-up commit — the KDoc example now uses a <version> placeholder instead of a hard-coded version, so it won't go stale on future bumps.
…ion-agnostic The example hard-coded 1.18.1, now stale after the 1.20.0 bump; use a <version> placeholder.
| val cryptGpgHomeName = | ||
| "crypt-gpg-" + layout.buildDirectory.get().asFile.absolutePath.hashCode().toUInt().toString(16) | ||
| gnupgHome.set(layout.dir(providers.provider { File(System.getProperty("java.io.tmpdir"), cryptGpgHomeName) })) |
There was a problem hiding this comment.
This is pre-existing code from commit 6e390ac (the gpg-homedir fix), not part of this PR's QE work. layout.buildDirectory is a stable provider and the hash is computed once at configuration time to derive a short, checkout-stable homedir name; realizing it here is low-risk. If configuration-cache hardening is wanted it'd be a separate, self-contained cleanup rather than part of the QE prefix/suffix/substring change.
| // Keep the scratch GPG keyring under the system temp dir, not the module build dir. gpg derives | ||
| // its agent socket path from the homedir, and macOS caps AF_UNIX socket paths (sun_path) at 104 | ||
| // bytes. A deeply-nested checkout pushes "<module>/build/jnaLibs/gnupg/S.gpg-agent" past that | ||
| // limit, so on a fresh keyring gpg fails ("can't connect to the gpg-agent: File name too long") | ||
| // and exits non-zero even though the import/verify would otherwise succeed. A short, | ||
| // checkout-independent homedir avoids this; the hash suffix isolates builds of different | ||
| // checkouts. verify() recreates this directory on every run, so a stable name is safe. |
There was a problem hiding this comment.
Good catch — fixed in 97ad4a2. The VerifyLibmongocryptTask KDoc now states the scratch keyring lives under the system temp dir (not build/) and that verify() recreates it each run so the trust state is always reset, matching the gnupgHome assignment.
The VerifyLibmongocryptTask KDoc still said the keyring lives under build/ and that clean resets trust; the homedir now lives under the system temp dir and verify() recreates it each run. Correct the comment to match.
Summary
Promotes Queryable Encryption string text queries from preview to GA and renames the public explicit-encryption API from "Text" to "String".
Text→String(DRIVERS-3321). Node analog: feat(NODE-7537): add QE String GA - renameTextPreviewtoString, sync spec tests node-mongodb-native#4972.Changes
Public API (
driver-core,com.mongodb.client.model.vault) — additive / backward compatible:StringOptions(@Alpha) mirroringTextOptions;TextOptionsretained and@Deprecated.EncryptOptions: addstringOptions(...)/getStringOptions(); deprecatetextOptions(...)/getTextOptions()(independent backing fields;stringOptionswins, falls back totextOptions)."TextPreview"→"String"; queryType now documentsprefix/suffix(GA) + the deprecatedprefixPreview/suffixPreviewaliases (pre-9.0) +substring/substringPreview. New API is@since 5.9.libmongocrypt:
1.18.1→1.20.0(stable prefix/suffix in 1.19.0, stable substring in 1.20.0). No JNA binding changes —mongocrypt_ctx_setopt_algorithm_textand its BSON schema are unchanged; only doc comments updated.Tests:
"String"+stringOptions, GA (prefix/suffix/substring, server 9.0+) vs preview (*Preview, pre-9.0) paths.QE-Text-substringGA unified spec test (now supported on libmongocrypt 1.20.0).main).Compatibility
No breaking changes — all additions or retained deprecations; no major version bump required. Note: passing
"TextPreview"as the algorithm value now errors at libmongocrypt (removed in 1.19.x); users must use"String".Testing
Evergreen patch (server
latest/9.0, libmongocrypt 1.20.0): prefix/suffix GA + substring GA prose + unified tests pass. A full-matrix patch showed only pre-existing (Windows CI) and flaky (connection-refused/timeout) failures, none related to these changes.Jira: https://jira.mongodb.org/browse/JAVA-6168